knitr::opts_chunk$set(echo = TRUE)
library(corrplot)
library(factoextra)
library(NbClust)
library(cluster)
library(plotly)
library(irr)
library(anytime)
library(dplyr)
library(ggdendro)
library(tidyverse)

Read in the Data

Correlation Matrix

corrplot(abs(cor(task_map[-1])), method = "shade",
         addCoef.col = TRUE,
         tl.col = "black", type = 'lower', diag = FALSE)

Descriptive Statistics

task_map[-1] %>% as.matrix() %>% mean()
[1] 0.4662973
task_map[-1] %>% as.matrix() %>% median()
[1] 0.4087121
task_map[-1] %>% as.matrix() %>% sd()
[1] 0.3707203
task_map[-1] %>% as.matrix() %>% range()
[1] 0 1

Confidence Judgements and Consensus

df.confidence_scores_raw <- df.mapping.raw %>%
  select(c(task, grep('confidence', names(df.mapping.raw)))) %>%
  pivot_longer(-task, names_to = "question") %>%
  mutate(
    value = recode(
    value,
    "Very confident" = 5,
    "Confident" = 4,
    "Neutral" = 3,
    "Not confident" = 2,
    "Not at all confident" =1
  )) %>%
  mutate(question = gsub("_confidence", "", question))

# This is z-scored by individual user
df.confidence_scores_zscore <- df.mapping.raw %>%
  select(c(task, user, grep('confidence', names(df.mapping.raw)))) %>%
  pivot_longer(-c(task, user), names_to = "question") %>%
  mutate(
    value = recode(
    value,
    "Very confident" = 5,
    "Confident" = 4,
    "Neutral" = 3,
    "Not confident" = 2,
    "Not at all confident" =1
  )) %>%
  group_by(user) %>%
  mutate(
    value = scale(value)
  ) %>% mutate(question = gsub("_confidence", "", question)) %>% ungroup()

There is a very strong correlation between the confidence scores and the level of agreement – about 0.77. This relationship holds regardless of whether you z-score the confidence scores (which helps to account for individual-level variation in assigning confidence).

# Task-based confidence
zscored_confidence_by_task <- df.confidence_scores_zscore %>%
  group_by(task) %>%
  summarize(
    mean_confidence = mean(value, na.rm = T)
  )

task_based_confidence <- inner_join(task_based_summary, zscored_confidence_by_task, by = "task")

cor.test(task_based_confidence$mean_agreement, task_based_confidence$mean_confidence)

    Pearson's product-moment correlation

data:  task_based_confidence$mean_agreement and task_based_confidence$mean_confidence
t = 10.281, df = 70, p-value = 1.246e-15
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.6631110 0.8538653
sample estimates:
      cor 
0.7756263 
# Question-based confidence
zscored_confidence_by_question <- df.confidence_scores_zscore %>%
  group_by(question) %>%
  summarize(
    mean_confidence = mean(value, na.rm = T)
  )

question_based_confidence <- inner_join(question_based_summary, zscored_confidence_by_question, by = c("question_name"="question"))

cor.test(question_based_confidence$mean_agreement, question_based_confidence$mean_confidence)

    Pearson's product-moment correlation

data:  question_based_confidence$mean_agreement and question_based_confidence$mean_confidence
t = 5.1162, df = 18, p-value = 7.224e-05
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.4963006 0.9042603
sample estimates:
      cor 
0.7697634 

A version of the above with the original ordinal variables (non-normalized)

# Task-based confidence
confidence_by_task <- df.confidence_scores_raw %>%
  group_by(task) %>%
  summarize(
    mean_confidence = mean(value, na.rm = T)
  )

task_based_confidence <- inner_join(task_based_summary, confidence_by_task, by = "task")

cor.test(task_based_confidence$mean_agreement, task_based_confidence$mean_confidence)

    Pearson's product-moment correlation

data:  task_based_confidence$mean_agreement and task_based_confidence$mean_confidence
t = 8.5847, df = 70, p-value = 1.531e-12
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.5808435 0.8129402
sample estimates:
      cor 
0.7161453 
# Question-based confidence
confidence_by_question <- df.confidence_scores_raw %>%
  group_by(question) %>%
  summarize(
    mean_confidence = mean(value, na.rm = T)
  )

question_based_confidence <- inner_join(question_based_summary, confidence_by_question, by = c("question_name"="question"))

cor.test(question_based_confidence$mean_agreement, question_based_confidence$mean_confidence)

    Pearson's product-moment correlation

data:  question_based_confidence$mean_agreement and question_based_confidence$mean_confidence
t = 5.2762, df = 18, p-value = 5.127e-05
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.5140589 0.9085150
sample estimates:
      cor 
0.7793026 
ggplot(task_based_confidence, 
       aes(x = mean_agreement,
           y = mean_confidence)) +
  geom_point() + 
  labs(title ="Per Task: Level of Rater Agreement v. Mean Normalized Rater Confidence")

Hierarchical Clustering

set_labels_params <- function(nbLabels,
                              direction = c("tb", "bt", "lr", "rl"),
                              fan       = FALSE) {
  if (fan) {
    angle       <-  360 / nbLabels * 1:nbLabels + 90
    idx         <-  angle >= 90 & angle <= 270
    angle[idx]  <-  angle[idx] + 180
    hjust       <-  rep(0, nbLabels)
    hjust[idx]  <-  1
  } else {
    angle       <-  rep(0, nbLabels)
    hjust       <-  0
    if (direction %in% c("tb", "bt")) { angle <- angle + 45 }
    if (direction %in% c("tb", "rl")) { hjust <- 1 }
  }
  list(angle = angle, hjust = hjust, vjust = 0.5)
}
dendro_data_k <- function(hc, k) {
  
  hcdata    <-  ggdendro::dendro_data(hc, type = "rectangle")
  seg       <-  hcdata$segments
  labclust  <-  cutree(hc, k)[hc$order]
  segclust  <-  rep(0L, nrow(seg))
  heights   <-  sort(hc$height, decreasing = TRUE)
  height    <-  mean(c(heights[k], heights[k - 1L]), na.rm = TRUE)
  
  for (i in 1:k) {
    xi      <-  hcdata$labels$x[labclust == i]
    idx1    <-  seg$x    >= min(xi) & seg$x    <= max(xi)
    idx2    <-  seg$xend >= min(xi) & seg$xend <= max(xi)
    idx3    <-  seg$yend < height
    idx     <-  idx1 & idx2 & idx3
    segclust[idx] <- i
  }
  
  idx                    <-  which(segclust == 0L)
  segclust[idx]          <-  segclust[idx + 1L]
  hcdata$segments$clust  <-  segclust
  hcdata$segments$line   <-  as.integer(segclust < 1L)
  hcdata$labels$clust    <-  labclust
  
  hcdata
}
plot_ggdendro <- function(hcdata,
                          direction   = c("lr", "rl", "tb", "bt"),
                          fan         = FALSE,
                          scale.color = NULL,
                          branch.size = 1,
                          label.size  = 3,
                          nudge.label = 0.01,
                          expand.y    = 0.1) {
  
  direction <- match.arg(direction) # if fan = FALSE
  ybreaks   <- pretty(segment(hcdata)$y, n = 5)
  ymax      <- max(segment(hcdata)$y)
  
  ## branches
  p <- ggplot() +
    geom_segment(data         =  segment(hcdata),
                 aes(x        =  x,
                     y        =  y,
                     xend     =  xend,
                     yend     =  yend,
                     linetype =  factor(line),
                     colour   =  factor(clust)),
                 lineend      =  "round",
                 show.legend  =  FALSE,
                 size         =  branch.size)
  
  ## orientation
  if (fan) {
    p <- p +
      coord_polar(direction = -1) +
      scale_x_continuous(breaks = NULL,
                         limits = c(0, nrow(label(hcdata)))) +
      scale_y_reverse(breaks = ybreaks)
  } else {
    p <- p + scale_x_continuous(breaks = NULL)
    if (direction %in% c("rl", "lr")) {
      p <- p + coord_flip()
    }
    if (direction %in% c("bt", "lr")) {
      p <- p + scale_y_reverse(breaks = ybreaks)
    } else {
      p <- p + scale_y_continuous(breaks = ybreaks)
      nudge.label <- -(nudge.label)
    }
  }
  
  # labels
  labelParams <- set_labels_params(nrow(hcdata$labels), direction, fan)
  hcdata$labels$angle <- labelParams$angle
  
  p <- p +
    geom_text(data        =  label(hcdata),
              aes(x       =  x,
                  y       =  y,
                  label   =  label,
                  colour  =  factor(clust),
                  angle   =  angle),
              vjust       =  labelParams$vjust,
              hjust       =  labelParams$hjust,
              nudge_y     =  ymax * nudge.label,
              size        =  label.size,
              show.legend =  FALSE)
  
  # colors and limits
  if (!is.null(scale.color)) {
    p <- p + scale_color_manual(values = scale.color)
  }
  
  ylim <- -round(ymax * expand.y, 1)
  p    <- p + expand_limits(y = ylim)
  
  p
}
set.seed(1)

# Dissimilarity matrix
d <- dist(task_map %>% column_to_rownames("task"), method = "euclidean")

# Hierarchical clustering using Complete Linkage
# Ward's method
hc5 <- hclust(d, method = "ward.D2" )

# get optimal number of clusters
NbClust(data = task_map %>% column_to_rownames("task"), distance = "euclidean", min.nc = 2, max.nc = 15, method = "ward.D2")
*** : The Hubert index is a graphical method of determining the number of clusters.
                In the plot of Hubert index, we seek a significant knee that corresponds to a 
                significant increase of the value of the measure i.e the significant peak in Hubert
                index second differences plot. 
 

*** : The D index is a graphical method of determining the number of clusters. 
                In the plot of D index, we seek a significant knee (the significant peak in Dindex
                second differences plot) that corresponds to a significant increase of the value of
                the measure. 
 
******************************************************************* 
* Among all indices:                                                
* 8 proposed 2 as the best number of clusters 
* 6 proposed 3 as the best number of clusters 
* 2 proposed 4 as the best number of clusters 
* 3 proposed 11 as the best number of clusters 
* 2 proposed 12 as the best number of clusters 
* 1 proposed 14 as the best number of clusters 
* 1 proposed 15 as the best number of clusters 

                   ***** Conclusion *****                            
 
* According to the majority rule, the best number of clusters is  2 
 
 
******************************************************************* 
$All.index
       KL      CH Hartigan     CCC     Scott Marriot  TrCovW  TraceW Friedman
2  2.7549 32.9128  14.2633 10.7304  600.0942  0.8292 24.2363 64.2186 2253.633
3  1.3224 26.5563  11.6289  7.8818  781.6212  0.1499 16.8037 53.3483 2388.235
4  1.4550 24.2083   8.6944  8.5778  882.3594  0.0658 10.9963 45.6540 2487.477
5  1.4615 22.3181   6.4038  9.3179  973.6377  0.0289  7.5798 40.4785 2601.855
6  0.9693 20.5307   6.7729  9.3506 1132.1170  0.0046  6.6994 36.9471 2895.586
7  1.4195 19.6905   5.1020  9.4864 1260.0349  0.0011  5.2321 33.5085 3364.848
8  0.9683 18.6399   5.3917  9.5818 1336.3086  0.0005  4.3205 31.0698 3490.919
9  1.1268 18.0711   4.9970  9.7785 1453.0660  0.0001  3.5107 28.6557 3625.514
10 1.0383 17.6085   4.9991  9.9450 1558.0244  0.0000  2.9226 26.5498 3826.166
11 0.9899 17.3411   5.2635 10.1924 1648.6200  0.0000  2.4316 24.5688 4220.981
12 1.6083 17.3148   3.5028 10.4000 1810.7186  0.0000  2.0846 22.6172 4863.753
13 1.0955 16.8056   3.2831 10.5764 1894.8189  0.0000  1.9193 21.3697 4893.967
14 0.9785 16.3468   3.4160 10.7074 2002.3501  0.0000  1.7617 20.2432 5177.165
15 0.9852 16.0358   3.5513 10.9101 2047.9786  0.0000  1.4892 19.1173 5296.495
     Rubin Cindex     DB Silhouette   Duda Pseudot2   Beale Ratkowsky    Ball
2   9.1488 0.4244 0.9297     0.4546 0.8080  14.7353  3.7648    0.3132 32.1093
3  11.0129 0.4504 1.3742     0.2494 0.7948  12.6534  4.0734    0.3220 17.7828
4  12.8690 0.4153 1.5590     0.2384 0.7349  12.9832  5.6480    0.3155 11.4135
5  14.5144 0.3789 1.5275     0.2004 0.5360   5.1941 11.9436    0.3032  8.0957
6  15.9017 0.3774 1.4894     0.2053 0.6652   5.5370  7.4270    0.2875  6.1579
7  17.5335 0.3570 1.3486     0.2245 0.7583   7.9684  4.9330    0.2774  4.7869
8  18.9098 0.3502 1.4456     0.1830 0.7073   4.5524  6.1063    0.2675  3.8837
9  20.5028 0.3213 1.4571     0.1937 0.5057   8.7956 14.1573    0.2579  3.1840
10 22.1291 0.3080 1.3709     0.2130 0.6376   3.9779  8.0035    0.2496  2.6550
11 23.9133 0.2979 1.3234     0.2171 0.7102   0.4081  3.2844    0.2458  2.2335
12 25.9767 0.3800 1.1764     0.2358 0.5116   2.8636 11.5233    0.2394  1.8848
13 27.4933 0.3927 1.1177     0.2416 0.6389   6.2171  8.3392    0.2337  1.6438
14 29.0231 0.3920 1.1179     0.2275 0.6594   3.0990  7.1259    0.2277  1.4459
15 30.7325 0.4353 1.1023     0.2296 0.7198   4.6705  5.7829    0.2218  1.2745
   Ptbiserial    Frey McClain   Dunn Hubert SDindex Dindex   SDbw
2      0.7595  4.5120  0.1327 0.4941 0.0432  3.8032 0.9038 0.8035
3      0.6162  1.0674  0.5206 0.3142 0.0403  4.4006 0.8246 0.7051
4      0.5812  1.4882  1.1004 0.2872 0.0400  4.6379 0.7649 0.6663
5      0.4932 -0.0187  1.9328 0.2361 0.0418  4.5730 0.7144 0.5898
6      0.5027  0.1139  1.9576 0.2415 0.0440  4.5232 0.6859 0.5684
7      0.5115  5.3953  2.0553 0.2415 0.0438  4.3465 0.6555 0.5208
8      0.4062  0.1203  3.4674 0.2342 0.0455  5.2113 0.6260 0.4872
9      0.4094  0.1380  3.7789 0.2342 0.0467  5.1822 0.6025 0.4795
10     0.4093  0.0912  3.9426 0.2342 0.0472  4.8603 0.5775 0.4170
11     0.4117 -0.0226  4.0927 0.2388 0.0472  4.7870 0.5591 0.3972
12     0.4141  0.1071  4.0898 0.2946 0.0473  4.3009 0.5366 0.3212
13     0.4145 16.6000  4.1449 0.3071 0.0473  4.2262 0.5230 0.3108
14     0.3782  0.1407  5.0287 0.3071 0.0482  4.2857 0.5041 0.2924
15     0.3762  0.1980  5.2227 0.3429 0.0490  4.5590 0.4922 0.2932

$All.CriticalValues
   CritValue_Duda CritValue_PseudoT2 Fvalue_Beale
2          0.8565            10.3906        0.000
3          0.8425             9.1578        0.000
4          0.8220             7.7974        0.000
5          0.6446             3.3077        0.000
6          0.7153             4.3791        0.000
7          0.7939             6.4882        0.000
8          0.7153             4.3791        0.000
9          0.6929             3.9896        0.000
10         0.6634             3.5522        0.000
11         0.4372             1.2873        0.003
12         0.5578             2.3781        0.000
13         0.7153             4.3791        0.000
14         0.6446             3.3077        0.000
15         0.7246             4.5606        0.000

$Best.nc
                    KL      CH Hartigan     CCC    Scott Marriot TrCovW TraceW
Number_clusters 2.0000  2.0000   4.0000 15.0000   3.0000  3.0000 3.0000  3.000
Value_Index     2.7549 32.9128   2.9346 10.9101 181.5271  0.5951 7.4326  3.176
                Friedman   Rubin  Cindex     DB Silhouette    Duda PseudoT2
Number_clusters  12.0000 12.0000 11.0000 2.0000     2.0000 11.0000  11.0000
Value_Index     642.7719 -0.5469  0.2979 0.9297     0.4546  0.7102   0.4081
                Beale Ratkowsky    Ball PtBiserial   Frey McClain   Dunn
Number_clusters    NA     3.000  3.0000     2.0000 4.0000  2.0000 2.0000
Value_Index        NA     0.322 14.3265     0.7595 1.4882  0.1327 0.4941
                Hubert SDindex Dindex    SDbw
Number_clusters      0  2.0000      0 14.0000
Value_Index          0  3.8032      0  0.2924

$Best.partition
                               Categorization problem 
                                                    1 
                                           Mastermind 
                                                    1 
                                        Logic Problem 
                                                    1 
                                               Sudoku 
                                                    1 
 Rank cities by population, rank words by familiarity 
                                                    1 
                                        Shopping plan 
                                                    1 
             Carter Racing (Experimenterless Version) 
                                                    1 
                        Iterative lemonade stand task 
                                                    1 
                         Reading the mind in the eyes 
                                                    1 
                                        Writing story 
                                                    2 
           Moral Reasoning (Disciplinary Action Case) 
                                                    2 
           Word construction from a subset of letters 
                                                    1 
                                        Carter Racing 
                                                    1 
                             Guessing the correlation 
                                                    1 
                      Wolf, goat and cabbage transfer 
                                                    1 
                                 Room assignment task 
                                                    1 
                                 Arithmetic problem 1 
                                                    1 
                                       Space Fortress 
                                                    1 
                                Visual Oddball Target 
                                                    1 
                               The N light bulbs game 
                                                    1 
                Word completion given starting letter 
                                                    1 
                     Railroad Route Construction game 
                                                    1 
                     Allocating resources to programs 
                                                    2 
                      Game of Clue - Terrorist Attack 
                                                    1 
                   Word completion given part of word 
                                                    1 
                                   NASA Moon survival 
                                                    1 
                                         Image rating 
                                                    1 
                        Estimating Factual Quantities 
                                                    1 
                                  Run a mini business 
                                                    1 
                                        Recall videos 
                                                    1 
                                  Search for Oil Task 
                                                    1 
                       To evacuate or not to evacuate 
                                                    1 
                        Estimating geological metrics 
                                                    1 
                      Euclidean traveling salesperson 
                                                    1 
                                     Reproducing arts 
                                                    1 
                           Estimating social quantity 
                                                    1 
         Hidden figures in a picture (Searching Task) 
                                                    1 
                           Estimating pages of a book 
                                                    1 
                                   Abstract grid task 
                                                    1 
                          Unscramble words (anagrams) 
                                                    1 
                                    Random dot motion 
                                                    1 
                                        Target Search 
                                                    1 
                                     Find the maximum 
                                                    1 
                       Wildcam Gorongosa (Zooniverse) 
                                                    1 
                                       Recall stories 
                                                    1 
                                   Recall association 
                                                    1 
           Letters-to-numbers problems (cryptography) 
                                                    1 
                            Architectural design task 
                                                    1 
                                    Recall word lists 
                                                    1 
                               Wason's Selection Task 
                                                    1 
                                 Summarize Discussion 
                                                    2 
                           Divergent Association Task 
                                                    2 
                                       Crisis mapping 
                                                    1 
                                        9 Dot Problem 
                                                    1 
                                        The Fish game 
                                                    1 
                                Advertisement writing 
                                                    2 
            Hidden figures in a picture (Recall Task) 
                                                    1 
                                        Computer maze 
                                                    1 
                            Splitting a deck of cards 
                                                    1 
    Object based generalization for reasoning (Phyre) 
                                                    1 
                                      Ravens Matrices 
                                                    1 
                          Trivia Multiple Choice Quiz 
                                                    1 
Railroad Route Construction game (Impossible Version) 
                                                    2 
                                      Desert survival 
                                                    1 
                         Putting food into categories 
                                                    2 
                                        Wildcat Wells 
                                                    1 
                                  Graph coloring task 
                                                    1 
                          Husbands and wives transfer 
                                                    1 
                                             Checkers 
                                                    1 
                                          Typing game 
                                                    1 
                                        Recall images 
                                                    1 
                                          Whac-A-Mole 
                                                    1 

# Plot the obtained dendrogram
colors = c( "#118AB2", "#A53860", "#073B4C", "#9071EE", "#209A92", "#3E885B", "#CC9328")
hcdata <- dendro_data_k(hc5, 2)
p <- plot_ggdendro(hcdata,
                   direction   = "lr",
                   scale.color = colors,
                   label.size  = 10,
                   branch.size = 2,
                   expand.y    = 4) + theme_void()
p

Look at “old taxonomies”

df.mcg <- task_map %>%
  select(
    task,
    Q1concept_behav,
    Q20type_3_type_4,
    Q3type_1_planning,
    Q4type_2_generate,
    Q6type_5_cc,
    Q7type_7_battle,
    Q8type_8_performance
  )
ggplot(
  df.mcg %>%
    rename(
      Physical = Q1concept_behav,
      Intellective = Q20type_3_type_4,
      Planning = Q3type_1_planning,
      Generative = Q4type_2_generate,
      `Cognitive Conflict` = Q6type_5_cc,
      Battle = Q7type_7_battle,
      Performance = Q8type_8_performance
    ) %>%
    pivot_longer(cols = -task) %>%
    rename(`Mean Rater Response` = value),
  aes(x = name, y = task)
) + geom_tile(aes(fill = `Mean Rater Response`)) + scale_fill_gradient(low = "#CC3363",
                                                       high = "#07BEB8") + theme(axis.text.x = element_text(
                                                         angle = 90,
                                                         vjust = 0.5,
                                                         hjust = 1
                                                       )) + 
  labs(x = "Dimension in McGrath's Taxonomy",
       y = "Task Name")


ggsave("26task-mcgrath-ratings.png")
Saving 7 x 9 in image

McGrath - within v. between-category variance

      Physical = Q1concept_behav,
      Intellective = Q20type_3_type_4,
      Planning = Q3type_1_planning,
      Generative = Q4type_2_generate,
      `Cognitive Conflict` = Q6type_5_cc,
      Battle = Q7type_7_battle,
      Performance = Q8type_8_performance

How much more information do we get when adding columns?

task_map_discrete <- cbind(task_map$task, discretize(task_map[-1], nbins = 10)) %>%
                        rename(task = `task_map$task`)

df.mcg <- task_map_discrete %>%
  select(
    task,
    Q1concept_behav,
    Q20type_3_type_4,
    Q3type_1_planning,
    Q4type_2_generate,
    Q6type_5_cc,
    Q7type_7_battle,
    Q8type_8_performance
  )
df.laughlin <- task_map_discrete %>%
  select(
    task,
    Q15dec_verifiability,
    Q16shared_knowledge,
    Q17within_sys_sol,
    Q18ans_recog,
    Q19time_solvability,
    Q21intellective_judg_1,
    Q24eureka_question
    )

df.shaw <- task_map_discrete %>%
  select(
    task,
    Q2intel_manip_1,
    Q13outcome_multip,
    Q14sol_scheme_mul
    )

df.steiner <- task_map_discrete %>%
 select(
    task,
    Q9divisible_unitary,
    Q10maximizing,
    Q11optimizing
    )

df.zigurs <- task_map_discrete %>%
 select(
    task,
    Q13outcome_multip,
    Q14sol_scheme_mul,
    Q22confl_tradeoffs,
    Q23ss_out_uncert
    )

for documentation, see: https://cran.r-project.org/web/packages/infotheo/infotheo.pdf

Confirming discretization still looks good (qualitatively)

pca <- task_map_discrete %>% #select(-continuous_questions) %>%
  select(-task) %>%
  prcomp(center = T)

kmeans_output <- pca$x %>% # 2 is the optimal number
  kmeans(centers = 3, nstart = 100)
combined_data <- cbind(task_map,
      pca$x, factor(kmeans_output$cluster)) %>%
  rename(cluster = `factor(kmeans_output$cluster)`)
         
plot_ly(
  x = combined_data$PC1,
  y = combined_data$PC2,
  z = combined_data$PC3,
  type = "scatter3d",
  mode = "markers", # can use mode = "text"
  text = combined_data$task ,
  color = combined_data$cluster
)
#total correlation (also known as multi-information)
multiinformation(task_map_discrete[-1])
[1] 44.50342
multiinformation(df.mcg[-1])
[1] 9.274719
multiinformation(df.laughlin[-1])
[1] 10.39968
multiinformation(df.shaw[-1])
[1] 2.64197
multiinformation(df.steiner[-1])
[1] 2.659127
multiinformation(df.zigurs[-1])
[1] 4.867023
# maybe don't run? takes forever, likely due to calculation of many conditional probabilities. also, negative and not interpretable
# interaction information
# interinformation(task_map_discrete[-1])
# interinformation(df.mcg[-1])
# interinformation(df.laughlin[-1])
# interinformation(df.shaw[-1])
# interinformation(df.steiner[-1])
# interinformation(df.zigurs[-1])

Notes on how this is supposed to work:

from https://arxiv.org/pdf/1701.08868.pdf > In the case of three random variables, interaction information is the gain (or loss) in information transmitted between any two of the variables, due to additional knowledge of the third random variable. That is, interaction information is the difference between the conditional and unconditional mutual information between two of the variables, where the conditioning is on the third variable. It is important to note that unlike (conditional) mutual information which is always non-negative, interaction information can be negative.

LS0tCnRpdGxlOiAibmV3LXRhc2stbWFwLWFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7cn0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpsaWJyYXJ5KGluZm90aGVvKQpsaWJyYXJ5KGNvcnJwbG90KQpsaWJyYXJ5KGZhY3RvZXh0cmEpCmxpYnJhcnkoTmJDbHVzdCkKbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeShpcnIpCmxpYnJhcnkoYW55dGltZSkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ2RlbmRybykKbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKUmVhZCBpbiB0aGUgRGF0YQpgYGB7cn0KZGYubWFwcGluZy5yYXcgPC0gcmVhZF9jc3YoJy4uL3Jhd19tYXAuY3N2JykKdGFza19tYXAgPC0gcmVhZF9jc3YoJy4uL3Rhc2tfbWFwLmNzdicpCmRmLm1haW5fcXVlc3Rpb25zX3N1bW1hcnkgPC0gcmVhZF9jc3YoJy4uL21haW5fcXVlc3Rpb25fc3VtbWFyeS5jc3YnKQoKdGFza19iYXNlZF9zdW1tYXJ5IDwtIGRmLm1haW5fcXVlc3Rpb25zX3N1bW1hcnkgJT4lCiAgZmlsdGVyKG5fbGFiZWxzID4gMTApICU+JQogIGdyb3VwX2J5KHRhc2ssIHRhc2tfYmxvYl91cmwpICU+JQogIHN1bW1hcml6ZSgKICAgIG1lYW5fYWdyZWVtZW50ID0gbWVhbihhZ3JlZW1lbnQpLAogICAgbWVhbl9hbHBoYSA9IG1lYW4oZ2VuZXJhbC5hbHBoYSkKICApICU+JQogIGFycmFuZ2UoZGVzYyhtZWFuX2FncmVlbWVudCkpCgp0YXNrX2Jhc2VkX3N1bW1hcnkKbWVhbih0YXNrX2Jhc2VkX3N1bW1hcnkkbWVhbl9hZ3JlZW1lbnQpCnNkKHRhc2tfYmFzZWRfc3VtbWFyeSRtZWFuX2FncmVlbWVudCkKcXVhbnRpbGUodGFza19iYXNlZF9zdW1tYXJ5JG1lYW5fYWdyZWVtZW50LCBjKDAuMDI1LCAwLjk3MjUpKQoKcXVlc3Rpb25fYmFzZWRfc3VtbWFyeSA8LSBkZi5tYWluX3F1ZXN0aW9uc19zdW1tYXJ5ICU+JQogIGZpbHRlcihuX2xhYmVscyA+IDEwKSAlPiUKICBncm91cF9ieShxdWVzdGlvbl9uYW1lKSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuX2FncmVlbWVudCA9IG1lYW4oYWdyZWVtZW50KSwKICAgIG1lYW5fYWxwaGEgPSBtZWFuKGdlbmVyYWwuYWxwaGEpCiAgKSAlPiUKICBhcnJhbmdlKGRlc2MobWVhbl9hZ3JlZW1lbnQpKQoKcXVlc3Rpb25fYmFzZWRfc3VtbWFyeQptZWFuKHF1ZXN0aW9uX2Jhc2VkX3N1bW1hcnkkbWVhbl9hZ3JlZW1lbnQpCnNkKHF1ZXN0aW9uX2Jhc2VkX3N1bW1hcnkkbWVhbl9hZ3JlZW1lbnQpCnF1YW50aWxlKHF1ZXN0aW9uX2Jhc2VkX3N1bW1hcnkkbWVhbl9hZ3JlZW1lbnQsIGMoMC4wMjUsIDAuOTcyNSksIG5hLnJtID0gVCkKYGBgCgoKIyBDb3JyZWxhdGlvbiBNYXRyaXgKYGBge3IgZmlnLmhlaWdodD0xMH0KY29ycnBsb3QoYWJzKGNvcih0YXNrX21hcFstMV0pKSwgbWV0aG9kID0gInNoYWRlIiwKICAgICAgICAgYWRkQ29lZi5jb2wgPSBUUlVFLAogICAgICAgICB0bC5jb2wgPSAiYmxhY2siLCB0eXBlID0gJ2xvd2VyJywgZGlhZyA9IEZBTFNFKQpgYGAKCgojIERlc2NyaXB0aXZlIFN0YXRpc3RpY3MKYGBge3J9CnRhc2tfbWFwWy0xXSAlPiUgYXMubWF0cml4KCkgJT4lIG1lYW4oKQp0YXNrX21hcFstMV0gJT4lIGFzLm1hdHJpeCgpICU+JSBtZWRpYW4oKQp0YXNrX21hcFstMV0gJT4lIGFzLm1hdHJpeCgpICU+JSBzZCgpCnRhc2tfbWFwWy0xXSAlPiUgYXMubWF0cml4KCkgJT4lIHJhbmdlKCkKYGBgCgojIENvbmZpZGVuY2UgSnVkZ2VtZW50cyBhbmQgQ29uc2Vuc3VzCgpgYGB7cn0KZGYuY29uZmlkZW5jZV9zY29yZXNfcmF3IDwtIGRmLm1hcHBpbmcucmF3ICU+JQogIHNlbGVjdChjKHRhc2ssIGdyZXAoJ2NvbmZpZGVuY2UnLCBuYW1lcyhkZi5tYXBwaW5nLnJhdykpKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKC10YXNrLCBuYW1lc190byA9ICJxdWVzdGlvbiIpICU+JQogIG11dGF0ZSgKICAgIHZhbHVlID0gcmVjb2RlKAogICAgdmFsdWUsCiAgICAiVmVyeSBjb25maWRlbnQiID0gNSwKICAgICJDb25maWRlbnQiID0gNCwKICAgICJOZXV0cmFsIiA9IDMsCiAgICAiTm90IGNvbmZpZGVudCIgPSAyLAogICAgIk5vdCBhdCBhbGwgY29uZmlkZW50IiA9MQogICkpICU+JQogIG11dGF0ZShxdWVzdGlvbiA9IGdzdWIoIl9jb25maWRlbmNlIiwgIiIsIHF1ZXN0aW9uKSkKCiMgVGhpcyBpcyB6LXNjb3JlZCBieSBpbmRpdmlkdWFsIHVzZXIKZGYuY29uZmlkZW5jZV9zY29yZXNfenNjb3JlIDwtIGRmLm1hcHBpbmcucmF3ICU+JQogIHNlbGVjdChjKHRhc2ssIHVzZXIsIGdyZXAoJ2NvbmZpZGVuY2UnLCBuYW1lcyhkZi5tYXBwaW5nLnJhdykpKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKC1jKHRhc2ssIHVzZXIpLCBuYW1lc190byA9ICJxdWVzdGlvbiIpICU+JQogIG11dGF0ZSgKICAgIHZhbHVlID0gcmVjb2RlKAogICAgdmFsdWUsCiAgICAiVmVyeSBjb25maWRlbnQiID0gNSwKICAgICJDb25maWRlbnQiID0gNCwKICAgICJOZXV0cmFsIiA9IDMsCiAgICAiTm90IGNvbmZpZGVudCIgPSAyLAogICAgIk5vdCBhdCBhbGwgY29uZmlkZW50IiA9MQogICkpICU+JQogIGdyb3VwX2J5KHVzZXIpICU+JQogIG11dGF0ZSgKICAgIHZhbHVlID0gc2NhbGUodmFsdWUpCiAgKSAlPiUgbXV0YXRlKHF1ZXN0aW9uID0gZ3N1YigiX2NvbmZpZGVuY2UiLCAiIiwgcXVlc3Rpb24pKSAlPiUgdW5ncm91cCgpCmBgYAoKVGhlcmUgaXMgYSB2ZXJ5IHN0cm9uZyBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBjb25maWRlbmNlIHNjb3JlcyBhbmQgdGhlIGxldmVsIG9mIGFncmVlbWVudCAtLSBhYm91dCAwLjc3LiBUaGlzIHJlbGF0aW9uc2hpcCBob2xkcyByZWdhcmRsZXNzIG9mIHdoZXRoZXIgeW91IHotc2NvcmUgdGhlIGNvbmZpZGVuY2Ugc2NvcmVzICh3aGljaCBoZWxwcyB0byBhY2NvdW50IGZvciBpbmRpdmlkdWFsLWxldmVsIHZhcmlhdGlvbiBpbiBhc3NpZ25pbmcgY29uZmlkZW5jZSkuCgpgYGB7cn0KIyBUYXNrLWJhc2VkIGNvbmZpZGVuY2UKenNjb3JlZF9jb25maWRlbmNlX2J5X3Rhc2sgPC0gZGYuY29uZmlkZW5jZV9zY29yZXNfenNjb3JlICU+JQogIGdyb3VwX2J5KHRhc2spICU+JQogIHN1bW1hcml6ZSgKICAgIG1lYW5fY29uZmlkZW5jZSA9IG1lYW4odmFsdWUsIG5hLnJtID0gVCkKICApCgp0YXNrX2Jhc2VkX2NvbmZpZGVuY2UgPC0gaW5uZXJfam9pbih0YXNrX2Jhc2VkX3N1bW1hcnksIHpzY29yZWRfY29uZmlkZW5jZV9ieV90YXNrLCBieSA9ICJ0YXNrIikKCmNvci50ZXN0KHRhc2tfYmFzZWRfY29uZmlkZW5jZSRtZWFuX2FncmVlbWVudCwgdGFza19iYXNlZF9jb25maWRlbmNlJG1lYW5fY29uZmlkZW5jZSkKCiMgUXVlc3Rpb24tYmFzZWQgY29uZmlkZW5jZQp6c2NvcmVkX2NvbmZpZGVuY2VfYnlfcXVlc3Rpb24gPC0gZGYuY29uZmlkZW5jZV9zY29yZXNfenNjb3JlICU+JQogIGdyb3VwX2J5KHF1ZXN0aW9uKSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuX2NvbmZpZGVuY2UgPSBtZWFuKHZhbHVlLCBuYS5ybSA9IFQpCiAgKQoKcXVlc3Rpb25fYmFzZWRfY29uZmlkZW5jZSA8LSBpbm5lcl9qb2luKHF1ZXN0aW9uX2Jhc2VkX3N1bW1hcnksIHpzY29yZWRfY29uZmlkZW5jZV9ieV9xdWVzdGlvbiwgYnkgPSBjKCJxdWVzdGlvbl9uYW1lIj0icXVlc3Rpb24iKSkKCmNvci50ZXN0KHF1ZXN0aW9uX2Jhc2VkX2NvbmZpZGVuY2UkbWVhbl9hZ3JlZW1lbnQsIHF1ZXN0aW9uX2Jhc2VkX2NvbmZpZGVuY2UkbWVhbl9jb25maWRlbmNlKQpgYGAKCkEgdmVyc2lvbiBvZiB0aGUgYWJvdmUgd2l0aCB0aGUgb3JpZ2luYWwgb3JkaW5hbCB2YXJpYWJsZXMgKG5vbi1ub3JtYWxpemVkKQpgYGB7cn0KIyBUYXNrLWJhc2VkIGNvbmZpZGVuY2UKY29uZmlkZW5jZV9ieV90YXNrIDwtIGRmLmNvbmZpZGVuY2Vfc2NvcmVzX3JhdyAlPiUKICBncm91cF9ieSh0YXNrKSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuX2NvbmZpZGVuY2UgPSBtZWFuKHZhbHVlLCBuYS5ybSA9IFQpCiAgKQoKdGFza19iYXNlZF9jb25maWRlbmNlIDwtIGlubmVyX2pvaW4odGFza19iYXNlZF9zdW1tYXJ5LCBjb25maWRlbmNlX2J5X3Rhc2ssIGJ5ID0gInRhc2siKQoKY29yLnRlc3QodGFza19iYXNlZF9jb25maWRlbmNlJG1lYW5fYWdyZWVtZW50LCB0YXNrX2Jhc2VkX2NvbmZpZGVuY2UkbWVhbl9jb25maWRlbmNlKQoKIyBRdWVzdGlvbi1iYXNlZCBjb25maWRlbmNlCmNvbmZpZGVuY2VfYnlfcXVlc3Rpb24gPC0gZGYuY29uZmlkZW5jZV9zY29yZXNfcmF3ICU+JQogIGdyb3VwX2J5KHF1ZXN0aW9uKSAlPiUKICBzdW1tYXJpemUoCiAgICBtZWFuX2NvbmZpZGVuY2UgPSBtZWFuKHZhbHVlLCBuYS5ybSA9IFQpCiAgKQoKcXVlc3Rpb25fYmFzZWRfY29uZmlkZW5jZSA8LSBpbm5lcl9qb2luKHF1ZXN0aW9uX2Jhc2VkX3N1bW1hcnksIGNvbmZpZGVuY2VfYnlfcXVlc3Rpb24sIGJ5ID0gYygicXVlc3Rpb25fbmFtZSI9InF1ZXN0aW9uIikpCgpjb3IudGVzdChxdWVzdGlvbl9iYXNlZF9jb25maWRlbmNlJG1lYW5fYWdyZWVtZW50LCBxdWVzdGlvbl9iYXNlZF9jb25maWRlbmNlJG1lYW5fY29uZmlkZW5jZSkKYGBgCgpgYGB7cn0KZ2dwbG90KHRhc2tfYmFzZWRfY29uZmlkZW5jZSwgCiAgICAgICBhZXMoeCA9IG1lYW5fYWdyZWVtZW50LAogICAgICAgICAgIHkgPSBtZWFuX2NvbmZpZGVuY2UpKSArCiAgZ2VvbV9wb2ludCgpICsgCiAgbGFicyh0aXRsZSA9IlBlciBUYXNrOiBMZXZlbCBvZiBSYXRlciBBZ3JlZW1lbnQgdi4gTWVhbiBOb3JtYWxpemVkIFJhdGVyIENvbmZpZGVuY2UiKQpgYGAKCkhpZXJhcmNoaWNhbCBDbHVzdGVyaW5nCmBgYHtyIGhpZGRlbiBnZ2RlbmRybyBwbG90dGluZyBmdW5jdGlvbn0Kc2V0X2xhYmVsc19wYXJhbXMgPC0gZnVuY3Rpb24obmJMYWJlbHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9IGMoInRiIiwgImJ0IiwgImxyIiwgInJsIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhbiAgICAgICA9IEZBTFNFKSB7CiAgaWYgKGZhbikgewogICAgYW5nbGUgICAgICAgPC0gIDM2MCAvIG5iTGFiZWxzICogMTpuYkxhYmVscyArIDkwCiAgICBpZHggICAgICAgICA8LSAgYW5nbGUgPj0gOTAgJiBhbmdsZSA8PSAyNzAKICAgIGFuZ2xlW2lkeF0gIDwtICBhbmdsZVtpZHhdICsgMTgwCiAgICBoanVzdCAgICAgICA8LSAgcmVwKDAsIG5iTGFiZWxzKQogICAgaGp1c3RbaWR4XSAgPC0gIDEKICB9IGVsc2UgewogICAgYW5nbGUgICAgICAgPC0gIHJlcCgwLCBuYkxhYmVscykKICAgIGhqdXN0ICAgICAgIDwtICAwCiAgICBpZiAoZGlyZWN0aW9uICVpbiUgYygidGIiLCAiYnQiKSkgeyBhbmdsZSA8LSBhbmdsZSArIDQ1IH0KICAgIGlmIChkaXJlY3Rpb24gJWluJSBjKCJ0YiIsICJybCIpKSB7IGhqdXN0IDwtIDEgfQogIH0KICBsaXN0KGFuZ2xlID0gYW5nbGUsIGhqdXN0ID0gaGp1c3QsIHZqdXN0ID0gMC41KQp9CmRlbmRyb19kYXRhX2sgPC0gZnVuY3Rpb24oaGMsIGspIHsKICAKICBoY2RhdGEgICAgPC0gIGdnZGVuZHJvOjpkZW5kcm9fZGF0YShoYywgdHlwZSA9ICJyZWN0YW5nbGUiKQogIHNlZyAgICAgICA8LSAgaGNkYXRhJHNlZ21lbnRzCiAgbGFiY2x1c3QgIDwtICBjdXRyZWUoaGMsIGspW2hjJG9yZGVyXQogIHNlZ2NsdXN0ICA8LSAgcmVwKDBMLCBucm93KHNlZykpCiAgaGVpZ2h0cyAgIDwtICBzb3J0KGhjJGhlaWdodCwgZGVjcmVhc2luZyA9IFRSVUUpCiAgaGVpZ2h0ICAgIDwtICBtZWFuKGMoaGVpZ2h0c1trXSwgaGVpZ2h0c1trIC0gMUxdKSwgbmEucm0gPSBUUlVFKQogIAogIGZvciAoaSBpbiAxOmspIHsKICAgIHhpICAgICAgPC0gIGhjZGF0YSRsYWJlbHMkeFtsYWJjbHVzdCA9PSBpXQogICAgaWR4MSAgICA8LSAgc2VnJHggICAgPj0gbWluKHhpKSAmIHNlZyR4ICAgIDw9IG1heCh4aSkKICAgIGlkeDIgICAgPC0gIHNlZyR4ZW5kID49IG1pbih4aSkgJiBzZWckeGVuZCA8PSBtYXgoeGkpCiAgICBpZHgzICAgIDwtICBzZWckeWVuZCA8IGhlaWdodAogICAgaWR4ICAgICA8LSAgaWR4MSAmIGlkeDIgJiBpZHgzCiAgICBzZWdjbHVzdFtpZHhdIDwtIGkKICB9CiAgCiAgaWR4ICAgICAgICAgICAgICAgICAgICA8LSAgd2hpY2goc2VnY2x1c3QgPT0gMEwpCiAgc2VnY2x1c3RbaWR4XSAgICAgICAgICA8LSAgc2VnY2x1c3RbaWR4ICsgMUxdCiAgaGNkYXRhJHNlZ21lbnRzJGNsdXN0ICA8LSAgc2VnY2x1c3QKICBoY2RhdGEkc2VnbWVudHMkbGluZSAgIDwtICBhcy5pbnRlZ2VyKHNlZ2NsdXN0IDwgMUwpCiAgaGNkYXRhJGxhYmVscyRjbHVzdCAgICA8LSAgbGFiY2x1c3QKICAKICBoY2RhdGEKfQpwbG90X2dnZGVuZHJvIDwtIGZ1bmN0aW9uKGhjZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gICA9IGMoImxyIiwgInJsIiwgInRiIiwgImJ0IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmFuICAgICAgICAgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZS5jb2xvciA9IE5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgYnJhbmNoLnNpemUgPSAxLAogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnNpemUgID0gMywKICAgICAgICAgICAgICAgICAgICAgICAgICBudWRnZS5sYWJlbCA9IDAuMDEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwYW5kLnkgICAgPSAwLjEpIHsKICAKICBkaXJlY3Rpb24gPC0gbWF0Y2guYXJnKGRpcmVjdGlvbikgIyBpZiBmYW4gPSBGQUxTRQogIHlicmVha3MgICA8LSBwcmV0dHkoc2VnbWVudChoY2RhdGEpJHksIG4gPSA1KQogIHltYXggICAgICA8LSBtYXgoc2VnbWVudChoY2RhdGEpJHkpCiAgCiAgIyMgYnJhbmNoZXMKICBwIDwtIGdncGxvdCgpICsKICAgIGdlb21fc2VnbWVudChkYXRhICAgICAgICAgPSAgc2VnbWVudChoY2RhdGEpLAogICAgICAgICAgICAgICAgIGFlcyh4ICAgICAgICA9ICB4LAogICAgICAgICAgICAgICAgICAgICB5ICAgICAgICA9ICB5LAogICAgICAgICAgICAgICAgICAgICB4ZW5kICAgICA9ICB4ZW5kLAogICAgICAgICAgICAgICAgICAgICB5ZW5kICAgICA9ICB5ZW5kLAogICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9ICBmYWN0b3IobGluZSksCiAgICAgICAgICAgICAgICAgICAgIGNvbG91ciAgID0gIGZhY3RvcihjbHVzdCkpLAogICAgICAgICAgICAgICAgIGxpbmVlbmQgICAgICA9ICAicm91bmQiLAogICAgICAgICAgICAgICAgIHNob3cubGVnZW5kICA9ICBGQUxTRSwKICAgICAgICAgICAgICAgICBzaXplICAgICAgICAgPSAgYnJhbmNoLnNpemUpCiAgCiAgIyMgb3JpZW50YXRpb24KICBpZiAoZmFuKSB7CiAgICBwIDwtIHAgKwogICAgICBjb29yZF9wb2xhcihkaXJlY3Rpb24gPSAtMSkgKwogICAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gTlVMTCwKICAgICAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMCwgbnJvdyhsYWJlbChoY2RhdGEpKSkpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKGJyZWFrcyA9IHlicmVha3MpCiAgfSBlbHNlIHsKICAgIHAgPC0gcCArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBOVUxMKQogICAgaWYgKGRpcmVjdGlvbiAlaW4lIGMoInJsIiwgImxyIikpIHsKICAgICAgcCA8LSBwICsgY29vcmRfZmxpcCgpCiAgICB9CiAgICBpZiAoZGlyZWN0aW9uICVpbiUgYygiYnQiLCAibHIiKSkgewogICAgICBwIDwtIHAgKyBzY2FsZV95X3JldmVyc2UoYnJlYWtzID0geWJyZWFrcykKICAgIH0gZWxzZSB7CiAgICAgIHAgPC0gcCArIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSB5YnJlYWtzKQogICAgICBudWRnZS5sYWJlbCA8LSAtKG51ZGdlLmxhYmVsKQogICAgfQogIH0KICAKICAjIGxhYmVscwogIGxhYmVsUGFyYW1zIDwtIHNldF9sYWJlbHNfcGFyYW1zKG5yb3coaGNkYXRhJGxhYmVscyksIGRpcmVjdGlvbiwgZmFuKQogIGhjZGF0YSRsYWJlbHMkYW5nbGUgPC0gbGFiZWxQYXJhbXMkYW5nbGUKICAKICBwIDwtIHAgKwogICAgZ2VvbV90ZXh0KGRhdGEgICAgICAgID0gIGxhYmVsKGhjZGF0YSksCiAgICAgICAgICAgICAgYWVzKHggICAgICAgPSAgeCwKICAgICAgICAgICAgICAgICAgeSAgICAgICA9ICB5LAogICAgICAgICAgICAgICAgICBsYWJlbCAgID0gIGxhYmVsLAogICAgICAgICAgICAgICAgICBjb2xvdXIgID0gIGZhY3RvcihjbHVzdCksCiAgICAgICAgICAgICAgICAgIGFuZ2xlICAgPSAgYW5nbGUpLAogICAgICAgICAgICAgIHZqdXN0ICAgICAgID0gIGxhYmVsUGFyYW1zJHZqdXN0LAogICAgICAgICAgICAgIGhqdXN0ICAgICAgID0gIGxhYmVsUGFyYW1zJGhqdXN0LAogICAgICAgICAgICAgIG51ZGdlX3kgICAgID0gIHltYXggKiBudWRnZS5sYWJlbCwKICAgICAgICAgICAgICBzaXplICAgICAgICA9ICBsYWJlbC5zaXplLAogICAgICAgICAgICAgIHNob3cubGVnZW5kID0gIEZBTFNFKQogIAogICMgY29sb3JzIGFuZCBsaW1pdHMKICBpZiAoIWlzLm51bGwoc2NhbGUuY29sb3IpKSB7CiAgICBwIDwtIHAgKyBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc2NhbGUuY29sb3IpCiAgfQogIAogIHlsaW0gPC0gLXJvdW5kKHltYXggKiBleHBhbmQueSwgMSkKICBwICAgIDwtIHAgKyBleHBhbmRfbGltaXRzKHkgPSB5bGltKQogIAogIHAKfQpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTEyfQpzZXQuc2VlZCgxKQoKIyBEaXNzaW1pbGFyaXR5IG1hdHJpeApkIDwtIGRpc3QodGFza19tYXAgJT4lIGNvbHVtbl90b19yb3duYW1lcygidGFzayIpLCBtZXRob2QgPSAiZXVjbGlkZWFuIikKCiMgSGllcmFyY2hpY2FsIGNsdXN0ZXJpbmcgdXNpbmcgQ29tcGxldGUgTGlua2FnZQojIFdhcmQncyBtZXRob2QKaGM1IDwtIGhjbHVzdChkLCBtZXRob2QgPSAid2FyZC5EMiIgKQoKIyBnZXQgb3B0aW1hbCBudW1iZXIgb2YgY2x1c3RlcnMKTmJDbHVzdChkYXRhID0gdGFza19tYXAgJT4lIGNvbHVtbl90b19yb3duYW1lcygidGFzayIpLCBkaXN0YW5jZSA9ICJldWNsaWRlYW4iLCBtaW4ubmMgPSAyLCBtYXgubmMgPSAxNSwgbWV0aG9kID0gIndhcmQuRDIiKQoKIyBQbG90IHRoZSBvYnRhaW5lZCBkZW5kcm9ncmFtCmNvbG9ycyA9IGMoICIjMTE4QUIyIiwgIiNBNTM4NjAiLCAiIzA3M0I0QyIsICIjOTA3MUVFIiwgIiMyMDlBOTIiLCAiIzNFODg1QiIsICIjQ0M5MzI4IikKaGNkYXRhIDwtIGRlbmRyb19kYXRhX2soaGM1LCAyKQpwIDwtIHBsb3RfZ2dkZW5kcm8oaGNkYXRhLAogICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uICAgPSAibHIiLAogICAgICAgICAgICAgICAgICAgc2NhbGUuY29sb3IgPSBjb2xvcnMsCiAgICAgICAgICAgICAgICAgICBsYWJlbC5zaXplICA9IDEwLAogICAgICAgICAgICAgICAgICAgYnJhbmNoLnNpemUgPSAyLAogICAgICAgICAgICAgICAgICAgZXhwYW5kLnkgICAgPSA0KSArIHRoZW1lX3ZvaWQoKQpwCmBgYAoKIyBMb29rIGF0ICJvbGQgdGF4b25vbWllcyIKCmBgYHtyfQpkZi5tY2cgPC0gdGFza19tYXAgJT4lCiAgc2VsZWN0KAogICAgdGFzaywKICAgIFExY29uY2VwdF9iZWhhdiwKICAgIFEyMHR5cGVfM190eXBlXzQsCiAgICBRM3R5cGVfMV9wbGFubmluZywKICAgIFE0dHlwZV8yX2dlbmVyYXRlLAogICAgUTZ0eXBlXzVfY2MsCiAgICBRN3R5cGVfN19iYXR0bGUsCiAgICBROHR5cGVfOF9wZXJmb3JtYW5jZQogICkKYGBgCgpgYGB7ciBmaWcuaGVpZ2h0PTksIGZpZy53aWR0aD03fQpnZ3Bsb3QoCiAgZGYubWNnICU+JQogICAgcmVuYW1lKAogICAgICBQaHlzaWNhbCA9IFExY29uY2VwdF9iZWhhdiwKICAgICAgSW50ZWxsZWN0aXZlID0gUTIwdHlwZV8zX3R5cGVfNCwKICAgICAgUGxhbm5pbmcgPSBRM3R5cGVfMV9wbGFubmluZywKICAgICAgR2VuZXJhdGl2ZSA9IFE0dHlwZV8yX2dlbmVyYXRlLAogICAgICBgQ29nbml0aXZlIENvbmZsaWN0YCA9IFE2dHlwZV81X2NjLAogICAgICBCYXR0bGUgPSBRN3R5cGVfN19iYXR0bGUsCiAgICAgIFBlcmZvcm1hbmNlID0gUTh0eXBlXzhfcGVyZm9ybWFuY2UKICAgICkgJT4lCiAgICBwaXZvdF9sb25nZXIoY29scyA9IC10YXNrKSAlPiUKICAgIHJlbmFtZShgTWVhbiBSYXRlciBSZXNwb25zZWAgPSB2YWx1ZSksCiAgYWVzKHggPSBuYW1lLCB5ID0gdGFzaykKKSArIGdlb21fdGlsZShhZXMoZmlsbCA9IGBNZWFuIFJhdGVyIFJlc3BvbnNlYCkpICsgc2NhbGVfZmlsbF9ncmFkaWVudChsb3cgPSAiI0NDMzM2MyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdoID0gIiMwN0JFQjgiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDkwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApKSArIAogIGxhYnMoeCA9ICJEaW1lbnNpb24gaW4gTWNHcmF0aCdzIFRheG9ub215IiwKICAgICAgIHkgPSAiVGFzayBOYW1lIikKCmdnc2F2ZSgiMjZ0YXNrLW1jZ3JhdGgtcmF0aW5ncy5wbmciKQpgYGAKCk1jR3JhdGggLSB3aXRoaW4gdi4gYmV0d2Vlbi1jYXRlZ29yeSB2YXJpYW5jZQpgYGAKICAgICAgUGh5c2ljYWwgPSBRMWNvbmNlcHRfYmVoYXYsCiAgICAgIEludGVsbGVjdGl2ZSA9IFEyMHR5cGVfM190eXBlXzQsCiAgICAgIFBsYW5uaW5nID0gUTN0eXBlXzFfcGxhbm5pbmcsCiAgICAgIEdlbmVyYXRpdmUgPSBRNHR5cGVfMl9nZW5lcmF0ZSwKICAgICAgYENvZ25pdGl2ZSBDb25mbGljdGAgPSBRNnR5cGVfNV9jYywKICAgICAgQmF0dGxlID0gUTd0eXBlXzdfYmF0dGxlLAogICAgICBQZXJmb3JtYW5jZSA9IFE4dHlwZV84X3BlcmZvcm1hbmNlCmBgYAoKIyBIb3cgbXVjaCBtb3JlIGluZm9ybWF0aW9uIGRvIHdlIGdldCB3aGVuIGFkZGluZyBjb2x1bW5zPwotIENhbGN1bGF0ZSBtdXR1YWwgaW5mb3JtYXRpb24gZm9yIGVhY2ggc3Vic2V0IChNY0dyYXRoLCBTdGVpbmVyLCBldGMuKQotIENvbXBhcmUgdG8gbXV0dWFsIGluZm9ybWF0aW9uIHdoZW4gdXNpbmcgYWxsIGNvbHVtbnMKLSBXZSBleHBlY3QgdGhlcmUgdG8gYmUgKm1vcmUgbXV0dWFsIGluZm9ybWF0aW9uKiB3aGVuIHdlIHVzZSBhbGwgY29sdW1ucyAKCmBgYHtyIHNldCB1cCBpbmRpdmlkdWFsIGRmcyBmb3IgZWFjaCBzb3VyY2UgcGFwZXJ9CnRhc2tfbWFwX2Rpc2NyZXRlIDwtIGNiaW5kKHRhc2tfbWFwJHRhc2ssIGRpc2NyZXRpemUodGFza19tYXBbLTFdLCBuYmlucyA9IDEwKSkgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmFtZSh0YXNrID0gYHRhc2tfbWFwJHRhc2tgKQoKZGYubWNnIDwtIHRhc2tfbWFwX2Rpc2NyZXRlICU+JQogIHNlbGVjdCgKICAgIHRhc2ssCiAgICBRMWNvbmNlcHRfYmVoYXYsCiAgICBRMjB0eXBlXzNfdHlwZV80LAogICAgUTN0eXBlXzFfcGxhbm5pbmcsCiAgICBRNHR5cGVfMl9nZW5lcmF0ZSwKICAgIFE2dHlwZV81X2NjLAogICAgUTd0eXBlXzdfYmF0dGxlLAogICAgUTh0eXBlXzhfcGVyZm9ybWFuY2UKICApCmRmLmxhdWdobGluIDwtIHRhc2tfbWFwX2Rpc2NyZXRlICU+JQogIHNlbGVjdCgKICAgIHRhc2ssCiAgICBRMTVkZWNfdmVyaWZpYWJpbGl0eSwKICAgIFExNnNoYXJlZF9rbm93bGVkZ2UsCiAgICBRMTd3aXRoaW5fc3lzX3NvbCwKICAgIFExOGFuc19yZWNvZywKICAgIFExOXRpbWVfc29sdmFiaWxpdHksCiAgICBRMjFpbnRlbGxlY3RpdmVfanVkZ18xLAogICAgUTI0ZXVyZWthX3F1ZXN0aW9uCiAgICApCgpkZi5zaGF3IDwtIHRhc2tfbWFwX2Rpc2NyZXRlICU+JQogIHNlbGVjdCgKICAgIHRhc2ssCiAgICBRMmludGVsX21hbmlwXzEsCiAgICBRMTNvdXRjb21lX211bHRpcCwKICAgIFExNHNvbF9zY2hlbWVfbXVsCiAgICApCgpkZi5zdGVpbmVyIDwtIHRhc2tfbWFwX2Rpc2NyZXRlICU+JQogc2VsZWN0KAogICAgdGFzaywKICAgIFE5ZGl2aXNpYmxlX3VuaXRhcnksCiAgICBRMTBtYXhpbWl6aW5nLAogICAgUTExb3B0aW1pemluZwogICAgKQoKZGYuemlndXJzIDwtIHRhc2tfbWFwX2Rpc2NyZXRlICU+JQogc2VsZWN0KAogICAgdGFzaywKICAgIFExM291dGNvbWVfbXVsdGlwLAogICAgUTE0c29sX3NjaGVtZV9tdWwsCiAgICBRMjJjb25mbF90cmFkZW9mZnMsCiAgICBRMjNzc19vdXRfdW5jZXJ0CiAgICApCmBgYApmb3IgZG9jdW1lbnRhdGlvbiwgc2VlOiBodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvaW5mb3RoZW8vaW5mb3RoZW8ucGRmCgpDb25maXJtaW5nIGRpc2NyZXRpemF0aW9uIHN0aWxsIGxvb2tzIGdvb2QgKHF1YWxpdGF0aXZlbHkpCmBgYHtyfQpwY2EgPC0gdGFza19tYXBfZGlzY3JldGUgJT4lICNzZWxlY3QoLWNvbnRpbnVvdXNfcXVlc3Rpb25zKSAlPiUKICBzZWxlY3QoLXRhc2spICU+JQogIHByY29tcChjZW50ZXIgPSBUKQoKa21lYW5zX291dHB1dCA8LSBwY2EkeCAlPiUgIyAyIGlzIHRoZSBvcHRpbWFsIG51bWJlcgogIGttZWFucyhjZW50ZXJzID0gMywgbnN0YXJ0ID0gMTAwKQpjb21iaW5lZF9kYXRhIDwtIGNiaW5kKHRhc2tfbWFwLAogICAgICBwY2EkeCwgZmFjdG9yKGttZWFuc19vdXRwdXQkY2x1c3RlcikpICU+JQogIHJlbmFtZShjbHVzdGVyID0gYGZhY3RvcihrbWVhbnNfb3V0cHV0JGNsdXN0ZXIpYCkKICAgICAgICAgCnBsb3RfbHkoCiAgeCA9IGNvbWJpbmVkX2RhdGEkUEMxLAogIHkgPSBjb21iaW5lZF9kYXRhJFBDMiwKICB6ID0gY29tYmluZWRfZGF0YSRQQzMsCiAgdHlwZSA9ICJzY2F0dGVyM2QiLAogIG1vZGUgPSAibWFya2VycyIsICMgY2FuIHVzZSBtb2RlID0gInRleHQiCiAgdGV4dCA9IGNvbWJpbmVkX2RhdGEkdGFzayAsCiAgY29sb3IgPSBjb21iaW5lZF9kYXRhJGNsdXN0ZXIKKQpgYGAKCgpgYGB7cn0KI3RvdGFsIGNvcnJlbGF0aW9uIChhbHNvIGtub3duIGFzIG11bHRpLWluZm9ybWF0aW9uKQptdWx0aWluZm9ybWF0aW9uKHRhc2tfbWFwX2Rpc2NyZXRlWy0xXSkKbXVsdGlpbmZvcm1hdGlvbihkZi5tY2dbLTFdKQptdWx0aWluZm9ybWF0aW9uKGRmLmxhdWdobGluWy0xXSkKbXVsdGlpbmZvcm1hdGlvbihkZi5zaGF3Wy0xXSkKbXVsdGlpbmZvcm1hdGlvbihkZi5zdGVpbmVyWy0xXSkKbXVsdGlpbmZvcm1hdGlvbihkZi56aWd1cnNbLTFdKQpgYGAKCmBgYHtyfQojIG1heWJlIGRvbid0IHJ1bj8gdGFrZXMgZm9yZXZlciwgbGlrZWx5IGR1ZSB0byBjYWxjdWxhdGlvbiBvZiBtYW55IGNvbmRpdGlvbmFsIHByb2JhYmlsaXRpZXMuIGFsc28sIG5lZ2F0aXZlIGFuZCBub3QgaW50ZXJwcmV0YWJsZQojIGludGVyYWN0aW9uIGluZm9ybWF0aW9uCiMgaW50ZXJpbmZvcm1hdGlvbih0YXNrX21hcF9kaXNjcmV0ZVstMV0pCiMgaW50ZXJpbmZvcm1hdGlvbihkZi5tY2dbLTFdKQojIGludGVyaW5mb3JtYXRpb24oZGYubGF1Z2hsaW5bLTFdKQojIGludGVyaW5mb3JtYXRpb24oZGYuc2hhd1stMV0pCiMgaW50ZXJpbmZvcm1hdGlvbihkZi5zdGVpbmVyWy0xXSkKIyBpbnRlcmluZm9ybWF0aW9uKGRmLnppZ3Vyc1stMV0pCmBgYAoKYGBge3J9CiMgZW50cm9weT8KZW50cm9weSh0YXNrX21hcF9kaXNjcmV0ZVstMV0pCmVudHJvcHkoZGYubWNnWy0xXSkKZW50cm9weShkZi5sYXVnaGxpblstMV0pCmVudHJvcHkoZGYuc2hhd1stMV0pCmVudHJvcHkoZGYuc3RlaW5lclstMV0pCmVudHJvcHkoZGYuemlndXJzWy0xXSkKYGBgCgoKTm90ZXMgb24gaG93IHRoaXMgaXMgc3VwcG9zZWQgdG8gd29yazoKCmZyb20gaHR0cHM6Ly9hcnhpdi5vcmcvcGRmLzE3MDEuMDg4NjgucGRmCj4gSW4gdGhlIGNhc2Ugb2YgdGhyZWUgcmFuZG9tIHZhcmlhYmxlcywgaW50ZXJhY3Rpb24KaW5mb3JtYXRpb24gaXMgdGhlIGdhaW4gKG9yIGxvc3MpIGluIGluZm9ybWF0aW9uIHRyYW5zbWl0dGVkIGJldHdlZW4gYW55IHR3byBvZiB0aGUgdmFyaWFibGVzLCBkdWUgdG8gYWRkaXRpb25hbCBrbm93bGVkZ2Ugb2YgdGhlIHRoaXJkIHJhbmRvbSB2YXJpYWJsZS4gVGhhdCBpcywgaW50ZXJhY3Rpb24gaW5mb3JtYXRpb24KaXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgY29uZGl0aW9uYWwgYW5kIHVuY29uZGl0aW9uYWwgbXV0dWFsIGluZm9ybWF0aW9uIGJldHdlZW4gdHdvIG9mIHRoZSB2YXJpYWJsZXMsIHdoZXJlIHRoZSBjb25kaXRpb25pbmcgaXMgb24gdGhlIHRoaXJkIHZhcmlhYmxlLiBJdCBpcyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHVubGlrZSAoY29uZGl0aW9uYWwpIG11dHVhbCBpbmZvcm1hdGlvbiB3aGljaCBpcyBhbHdheXMgbm9uLW5lZ2F0aXZlLCBpbnRlcmFjdGlvbiBpbmZvcm1hdGlvbiBjYW4gYmUgbmVnYXRpdmUuCgoKCgo=